package com.iotechn.unimall.app.api.integralactivity;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.iotechn.unimall.biz.service.integral.IntegralBizService;
import com.iotechn.unimall.biz.service.turntable.TurnTableBiz;
import com.iotechn.unimall.core.exception.AppServiceException;
import com.iotechn.unimall.core.exception.ExceptionDefinition;
import com.iotechn.unimall.core.exception.ServiceException;
import com.iotechn.unimall.core.util.DateUtils;
import com.iotechn.unimall.data.component.LockComponent;
import com.iotechn.unimall.data.domain.*;
import com.iotechn.unimall.data.dto.UserDTO;
import com.iotechn.unimall.data.dto.integralactivity.IntegralConponDTO;
import com.iotechn.unimall.data.dto.integralactivity.IntegralGoodsDTO;
import com.iotechn.unimall.data.dto.integralactivity.InviteLogMiniAppDTO;
import com.iotechn.unimall.data.enums.*;
import com.iotechn.unimall.data.enums.coupon.CouponAvailableType;
import com.iotechn.unimall.data.enums.turntable.TurnTableTimesSonType;
import com.iotechn.unimall.data.enums.turntable.TurnTableTimesType;
import com.iotechn.unimall.data.mapper.*;
import com.iotechn.unimall.data.util.SessionUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class IntegralActivityServiceImpl implements IntegralActivityService {
    @Autowired
    private IntegralGoodsMapper integralGoodsMapper;
    @Autowired
    private IntegralUserMapper integralUserMapper;
    @Autowired
    private ImgMapper imgMapper;
    @Autowired
    private IntegralDetailMapper integralDetailMapper;
    @Autowired
    IntegralBizService integralBizService;
    @Autowired
    private CouponMapper couponMapper;
    @Autowired
    private TurntableUserMapper turntableUserMapper;
    @Autowired
    private InviteLogMapper inviteLogMapper;
    @Autowired
    private TurnTableBiz turnTableBiz;

    @Autowired
    private RewardLadderMapper rewardLadderMapper;

    @Autowired
    private UserCouponMapper userCouponMapper;

    @Autowired
    private LockComponent lockComponent;
    @Autowired
    private SkuMapper skuMapper;

    @Autowired
    private SpuMapper spuMapper;

    private static final Logger logger = LoggerFactory.getLogger(IntegralActivityServiceImpl.class);


    private static final String COUPON_LOCK = "COUPON_LOCK_";

    private static final String COUPON_USER_LOCK = "COUPON_USER_LOCK_";


    /**
     *  查看所有可以兑换的商品列表
     * @return
     * @throws ServiceException
     */
    @Override
    public List<IntegralGoodsDTO> IntegralGoodsList() throws ServiceException {
        Wrapper<IntegralGoodsDO> wrapper = new EntityWrapper<IntegralGoodsDO>();
        wrapper.eq("goods_type", IntegralGoodsType.EXCHANGEGOOD.getCode());
        wrapper.eq("status", 1);
        List<IntegralGoodsDO> integralGoodsDOS = integralGoodsMapper.selectList(wrapper);
        List<Long> spuList=new ArrayList<>();
        for (IntegralGoodsDO  integralGoodsDO:  integralGoodsDOS) {
            spuList.add(integralGoodsDO.getSpuId());
        }
        List<Long> skuList=new ArrayList<>();
        for (IntegralGoodsDO  integralGoodsDO:  integralGoodsDOS) {
            skuList.add(integralGoodsDO.getSkuId());
        }
        Wrapper<SpuDO> spuWrapper = new EntityWrapper<SpuDO>();
        spuWrapper.in("id",spuList);
        List<SpuDO> spuDOS = spuMapper.selectList(spuWrapper);
        Map<Long, SpuDO> spuDOSMap = spuDOS.stream().collect(Collectors.toMap(SpuDO::getId, spuDO -> spuDO));

        Wrapper<SkuDO> skuWrapper = new EntityWrapper<SkuDO>();
        skuWrapper.in("id",skuList);
        List<SkuDO> skuDOS = skuMapper.selectList(skuWrapper);
        Map<Long, SkuDO> skuDOSMap = skuDOS.stream().collect(Collectors.toMap(SkuDO::getId, skuDO -> skuDO));
        List<IntegralGoodsDTO> integralGoodsDTOS = new ArrayList<IntegralGoodsDTO>();
        for (IntegralGoodsDO integralGoodsDO : integralGoodsDOS
        ) {
            IntegralGoodsDTO integralGoodsDTO = new IntegralGoodsDTO();
            BeanUtils.copyProperties(integralGoodsDO, integralGoodsDTO);
            SpuDO spuDO = spuDOSMap.get(integralGoodsDO.getSpuId());
            integralGoodsDTO.setImg(spuDO.getImg());
            integralGoodsDTO.setSpuTitle(spuDO.getTitle());
            SkuDO skuDO = skuDOSMap.get(integralGoodsDO.getSkuId());
            integralGoodsDTO.setUnit(spuDO.getUnit());
            integralGoodsDTO.setSkuTitle(skuDO.getTitle());
            integralGoodsDTO.setIntegerGoodsId(integralGoodsDO.getId());
            integralGoodsDTOS.add(integralGoodsDTO);
        }
        return integralGoodsDTOS;
    }
    /**
     *  查看所有可以兑换的商品列表
     * @return
     * @throws ServiceException
     */
    @Override
    public IntegralGoodsDTO IntegralGoodsDetail(Long goodsDetailId) throws ServiceException {
            IntegralGoodsDO integralGoodsDO=integralGoodsMapper.selectById(goodsDetailId);
            IntegralGoodsDTO integralGoodsDTO = new IntegralGoodsDTO();
            if(integralGoodsDO!=null){
                BeanUtils.copyProperties(integralGoodsDO, integralGoodsDTO);

                SpuDO spuDO = spuMapper.selectById(integralGoodsDO.getSpuId());
                if(spuDO!=null){
                    integralGoodsDTO.setImg(spuDO.getImg());
                    integralGoodsDTO.setSpuTitle(spuDO.getTitle());
                    integralGoodsDTO.setUnit(spuDO.getUnit());
                    integralGoodsDTO.setDetail(spuDO.getDetail());
                    integralGoodsDTO.setImgList(imgMapper.getImgs(BizType.GOODS.getCode(), spuDO.getId()));
                    List<SkuDO> skuDOList = skuMapper.selectList(
                            new EntityWrapper<SkuDO>()
                                    .eq("spu_id", spuDO.getId()));
                }

                SkuDO skuDO = skuMapper.selectById(integralGoodsDO.getSkuId());
                if(skuDO!=null){
                    integralGoodsDTO.setSkuTitle(skuDO.getTitle());
                    integralGoodsDTO.setStock(skuDO.getStock());
                }
                integralGoodsDTO.setIntegerGoodsId(integralGoodsDO.getId());
            }

            return integralGoodsDTO;
    }
    /**
     * 查看所有可以兑换的优惠券
     * @throws ServiceException
     */
    @Override
    public List<Object> IntegralCouponList(Long userId) throws ServiceException {
        Wrapper<IntegralGoodsDO> wrapper = new EntityWrapper<IntegralGoodsDO>();
        wrapper.eq("status", 1);
        List<IntegralGoodsDO> integralGoodsDOS = integralGoodsMapper.selectList(wrapper);
        List<Long> conponList=new ArrayList<>();
        for (IntegralGoodsDO  integralGoodsDO:  integralGoodsDOS) {
            conponList.add(integralGoodsDO.getConponId());
        }
        //查看我的优惠券情况
        Wrapper<IntegralDetailDO> detailDOWrapperwrapper = new EntityWrapper<IntegralDetailDO>();
        detailDOWrapperwrapper.eq("user_id",userId);
        detailDOWrapperwrapper.eq("type",IntegralType.SPEND.getCode());
        detailDOWrapperwrapper.eq("son_type",IntegralSonType.COUPON.getCode());
        detailDOWrapperwrapper.in("type_id",conponList);
        List<IntegralDetailDO> integralDetailDOList=integralDetailMapper.selectList(detailDOWrapperwrapper);
        Map<Long, Integer> map = new HashMap<Long, Integer>();
        for(IntegralDetailDO item: integralDetailDOList){
            if(map.containsKey(item.getTypeId())){
                map.put(item.getTypeId(), map.get(item.getTypeId()).intValue() + 1);
            }else{
                map.put(item.getTypeId(), new Integer(1));
            }
        }
        Wrapper<CouponDO> couponWrapper = new EntityWrapper<CouponDO>();
        couponWrapper.in("id",conponList);
        List<CouponDO> tmp = couponMapper.selectList(couponWrapper);
        List<CouponDO> spuDOS=new ArrayList<>();
        for ( CouponDO couponDO:tmp
             ) {
            if(couponDO.getGmtStart()!=null || couponDO.getGmtEnd()!=null){
                if(couponDO.getGmtEnd().after(new Date())){
                    spuDOS.add(couponDO);
                }
            }
            if(couponDO.getGmtStart() == null && couponDO.getGmtEnd()==null){
                spuDOS.add(couponDO);
            }
        }
        Map<Long, CouponDO> spuDOSMap = spuDOS.stream().collect(Collectors.toMap(CouponDO::getId, spuDO -> spuDO));
        List<Object> integralGoodsDTOS = new ArrayList<Object>();
        //处理优惠券
        for (IntegralGoodsDO integralGoodsDO : integralGoodsDOS
        ) {
            IntegralConponDTO integralGoodsDTO = new IntegralConponDTO();
            BeanUtils.copyProperties(integralGoodsDO, integralGoodsDTO);
            CouponDO couponDO = spuDOSMap.get(integralGoodsDO.getConponId());
            if(couponDO == null){
                continue;
            }
            integralGoodsDTO.setCouponDO(couponDO);
            integralGoodsDTO.setIntegerGoodsId(integralGoodsDO.getId());
            integralGoodsDTO.setMyCount(0);
            if(map.get(integralGoodsDO.getConponId())!=null){
                integralGoodsDTO.setMyCount(map.get(integralGoodsDO.getConponId()));
            }
            integralGoodsDTO.setAvailable(CouponAvailableType.AVAILABLE.getCode());
            if(integralGoodsDTO.getMyCount().intValue() >= integralGoodsDTO.getSkuLimit().intValue()){
                integralGoodsDTO.setAvailable(CouponAvailableType.NO_AVAILABLE.getCode());
            }
            integralGoodsDTO.setIgoodsImgs(integralGoodsDO.getIgoodsImgs());
            integralGoodsDTOS.add(integralGoodsDTO);
        }
        //处理转盘抽奖
        for (IntegralGoodsDO integralGoodsDO : integralGoodsDOS
        ) {
            if(integralGoodsDO.getGoodsType().intValue() == IntegralGoodsType.EXCHANGETURNTAB.getCode()){
                integralGoodsDO.setGoodsName("积分兑换抽奖次数");
                integralGoodsDO.setIntegerGoodsId(integralGoodsDO.getId());
                integralGoodsDTOS.add(integralGoodsDO);
            }
        }
        return integralGoodsDTOS;
    }
    /**
     * 兑换优惠券
     * @throws ServiceException
     */
    @Override
    public Object exchangeCoupon(Long IntegralGoodsId,Long userId) throws ServiceException {
         //兑换优惠券
        //用户积分减少
        //详情记录增加
        //优惠券给用户
        //优惠券减少
        //防止用户一瞬间提交两次表单，导致超领
        UserDTO userDTO=SessionUtil.getUser();
        IntegralGoodsDO integralGoodsDO=integralGoodsMapper.selectById(IntegralGoodsId);
         if(integralGoodsDO==null || integralGoodsDO.getStatus()!=1){
             throw new AppServiceException(ExceptionDefinition.COUPON_ISSUE_OVER);
         }
         //兑换优惠券
         if(integralGoodsDO.getGoodsType().intValue() == IntegralGoodsType.EXCHANGECOUPON.getCode()){
            return exchangeCouponFun(integralGoodsDO,userDTO,userId);
         }
         if(integralGoodsDO.getGoodsType().intValue() == IntegralGoodsType.EXCHANGETURNTAB.getCode()){
             return exchangeTurntableTimes(IntegralGoodsId,userId);
         }
        return false;
    }

    /**
     * 兑换商品
     * @throws ServiceException
     */
    @Override
    public void exchangeGoods(Long IntegralGoodsId,Long goodsId,Long userId) throws ServiceException {

    }
    /**
     * 查看用户的积分信息
     * @param userId
     * @return
     * @throws ServiceException
     */
    @Override
    public IntegralUserDO getUserDoByUserId(Long userId) throws ServiceException {
        UserDTO userDTO=SessionUtil.getUser();
        Wrapper<IntegralUserDO> wrapper = new EntityWrapper<IntegralUserDO>();
        wrapper.eq("user_id", userDTO.getId());
        List<IntegralUserDO> integralGoodsDOS = integralUserMapper.selectList(wrapper);
        if(integralGoodsDOS!=null && integralGoodsDOS.size()>0){
            return integralGoodsDOS.get(0);
        }else{
            IntegralUserDO integralUserDO=new IntegralUserDO();
            integralUserDO.setUserId(userDTO.getId());
            integralUserDO.setCurrentIntegral(0);
            integralUserDO.setTotalIntegral(0);
            return integralUserDO;
        }
    }


    @Override
    public List<RewardLadderDO> getInvitereward(Long userId) throws ServiceException {
        List<RewardLadderDO> rewardLadderDOS = rewardLadderMapper.selectList(new EntityWrapper<RewardLadderDO>().eq("type", IntegralSonType.INVITE.getCode()));
        return rewardLadderDOS;
    }

    @Override
    public List<InviteLogMiniAppDTO> getInviteSuccessList(Long userId) throws ServiceException {
        List<InviteLogMiniAppDTO> inviteUserList = inviteLogMapper.getInviteUserList(userId);
        return inviteUserList;
    }


    /**
     * 兑换抽奖次数
     * @param IntegralGoodsId
     * @param userId
     * @return
     * @throws ServiceException
     */
    public Integer exchangeTurntableTimes(Long IntegralGoodsId,Long userId) throws ServiceException {
        TurntableUserDO turntableUserDOCurr= null;
        TurntableUserDO turntableUserDOOrig= null;

        IntegralGoodsDO integralGoodsDO=integralGoodsMapper.selectById(IntegralGoodsId);
        List<IntegralUserDO> integralUserDOS = integralUserMapper.selectList(new EntityWrapper<IntegralUserDO>().eq("user_id", userId));
        IntegralUserDO integralUserDO = integralUserDOS.get(0);
        if(integralUserDO.getCurrentIntegral().intValue() < integralGoodsDO.getIntegral().intValue()) {
            throw new AppServiceException(ExceptionDefinition.INTEGRAL_USERNOT_ENOUGH);
        }
        //消耗积分
        integralBizService.decIntegralDetail( integralGoodsDO,integralUserDO, IntegralType.SPEND.getCode(), IntegralSonType.FEE.getCode(),0L,"兑换抽奖次数");
        //添加抽奖次数
        List<TurntableUserDO> turntableUserDOS = turntableUserMapper.selectList(new EntityWrapper<TurntableUserDO>().eq("user_id", userId));
        if(turntableUserDOS == null || turntableUserDOS.size() < 1) {
            turntableUserDOOrig = turnTableBiz.makeNewTurntableUser(userId);
            turntableUserDOCurr = turnTableBiz.makeNewTurntableUser(userId);
        }
        if(turntableUserDOS != null && turntableUserDOS.size() > 0){
            turntableUserDOOrig = turntableUserDOS.get(0);
            turntableUserDOCurr = turntableUserDOS.get(0);
        }
        turntableUserDOCurr.setLuckDrawNum(turntableUserDOOrig.getLuckDrawNum()+1);
        turntableUserMapper.updateById(turntableUserDOCurr);
        //记录流水
        turnTableBiz.insertTurntableUserLog(turntableUserDOOrig,turntableUserDOCurr, TurnTableTimesType.INCREASE.getCode(), TurnTableTimesSonType.EXCHANGE.getCode(),0L,0L,"积分兑换抽奖次数");
        return turntableUserDOCurr.getLuckDrawNum();
    }


    public Boolean exchangeCouponFun(IntegralGoodsDO integralGoodsDO,UserDTO userDTO,Long userId) throws AppServiceException {
        Long couponId =integralGoodsDO.getConponId();
        IntegralUserDO integralUserDO=new IntegralUserDO();
        integralUserDO.setUserId(userDTO.getId());
        integralUserDO=integralUserMapper.selectOne(integralUserDO);
        if(integralUserDO==null || integralUserDO.getCurrentIntegral().intValue()<integralGoodsDO.getIntegral().intValue()){
            throw new AppServiceException(ExceptionDefinition.INTEGRAL_USERNOT_ENOUGH);
        }
        if (lockComponent.tryLock(COUPON_USER_LOCK + userId + "_" + couponId, 10)) {
            try {
                CouponDO couponDO = couponMapper.selectById(couponId);
                if (couponDO.getStatus() == StatusType.LOCK.getCode()) {
                    throw new AppServiceException(ExceptionDefinition.COUPON_HAS_LOCKED);
                }
                Date now = new Date();
                if (couponDO.getGmtEnd() != null && couponDO.getGmtEnd().getTime() < now.getTime()) {
                    throw new AppServiceException(ExceptionDefinition.COUPON_ACTIVITY_HAS_END);
                }
                if (couponDO.getGmtStart() != null && couponDO.getGmtStart().getTime() > now.getTime()) {
                    throw new AppServiceException(ExceptionDefinition.COUPON_ACTIVITY_NOT_START);
                }
                if (couponDO.getTotal() != -1 && couponDO.getSurplus() <= 0) {
                    throw new AppServiceException(ExceptionDefinition.COUPON_ISSUE_OVER);
                } else {
                    if (couponDO.getTotal() >= 0) {
                        if (couponDO.getSurplus() == 1) {
                            if (!lockComponent.tryLock(COUPON_LOCK + couponId, 10)) {
                                throw new AppServiceException(ExceptionDefinition.COUPON_ISSUE_OVER);
                            }
                        }
                        couponMapper.decCoupon(couponId);
                    }
                }


                if (integralGoodsDO.getSkuLimit() != -1) {
                    //校验用户是否已经领了
                    Integer count = userCouponMapper.selectCount(
                            new EntityWrapper<UserCouponDO>()
                                    .eq("user_id", userId)
                                    .eq("coupon_id", couponId));

                    if (count >= integralGoodsDO.getSkuLimit()) {
                        throw new AppServiceException(ExceptionDefinition.INTEGRAL_COUPON_PURCHASE_UPPER);
                    }
                }
                //判断积分是否可以  兑换
                IntegralUserDO currentUserMessage=new IntegralUserDO();
                Wrapper<IntegralUserDO> integralGoodsUserWrapper = new EntityWrapper<IntegralUserDO>();
                integralGoodsUserWrapper.eq("user_id",userId);
                List<IntegralUserDO> integralUserDOS = integralUserMapper.selectList(integralGoodsUserWrapper);
                if(integralUserDOS == null || integralUserDOS.size() < 1){
                    throw new AppServiceException(ExceptionDefinition.INTEGRAL_USERNOT_ENOUGH);
                }
                currentUserMessage=integralUserDOS.get(0);
                if(currentUserMessage.getCurrentIntegral() - integralGoodsDO.getIntegral() < 0){
                    throw new AppServiceException(ExceptionDefinition.INTEGRAL_USERNOT_ENOUGH);
                }

                //领取优惠券
                UserCouponDO userCouponDO = new UserCouponDO();
                userCouponDO.setUserId(userId);
                userCouponDO.setCouponId(couponId);
                if (couponDO.getGmtStart() != null && couponDO.getGmtEnd() != null) {
                    //如果优惠券是按区间领取的
                    userCouponDO.setGmtStart(couponDO.getGmtStart());
                    userCouponDO.setGmtEnd(couponDO.getGmtEnd());
                } else if (couponDO.getDays() != null) {
                    //如果是任意领取的，则从当前时间 加上 可用天数
                    userCouponDO.setGmtStart(now);
                    userCouponDO.setGmtEnd(DateUtils.getBeforeSomeDaysDate(now,couponDO.getDays()));
                } else {
                    throw new AppServiceException(ExceptionDefinition.COUPON_STRATEGY_INCORRECT);
                }

                userCouponDO.setGmtUpdate(now);
                userCouponDO.setGmtCreate(now);

                if(userCouponMapper.insert(userCouponDO)>0){
                    String title=couponDO.getTitle();
                    integralBizService.decIntegralDetail( integralGoodsDO,integralUserDO,IntegralType.SPEND.getCode(),IntegralSonType.COUPON.getCode(),couponId,title);
                }
                return true;
            } catch (ServiceException e) {
                throw e;
            } catch (Exception e) {
                logger.error("[领取优惠券] 异常", e);
                throw new AppServiceException(ExceptionDefinition.APP_UNKNOWN_EXCEPTION);
            } finally {
                lockComponent.retree(COUPON_USER_LOCK + userId + "_" + couponId);
            }
        } else {
            throw new AppServiceException(ExceptionDefinition.SYSTEM_BUSY);
        }
    }
}
